import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TaskOperations {
	/*
	 * TODO: This class needs major refactoring. Methods should be more modular and meaningful
	 * identifiers should be used. 
	 */
	
	private static final String ERROR_INVALID_INPUT = "invalid input";

	public TaskOperations(UserInputElements userInputElements,
			List<Task> tasksInTempStorage, List<Task> tasksOnDisplay,
			String typeTasksOnDisplay, List<List<Task>> snapshotOfTasks) {

		String newTypeTasksOnDisplay = initializeSystem(userInputElements,
				tasksInTempStorage, tasksOnDisplay, typeTasksOnDisplay);
		TaskO.taskList.typeTasksOnDisplay = newTypeTasksOnDisplay;
		executeCommand(userInputElements, tasksInTempStorage, tasksOnDisplay,
				newTypeTasksOnDisplay, snapshotOfTasks);
		prepareForUndo(userInputElements, tasksInTempStorage, snapshotOfTasks);
	}

	private String initializeSystem(UserInputElements userInputElements,
			List<Task> tasksInTempStorage, List<Task> tasksOnDisplay,
			String typeTasksOnDisplay) {
		String taskAction = userInputElements.getTaskAction().name();
		String newTypeTasksOnDisplay = "";

		// first run case
		if (typeTasksOnDisplay == "") {
			newTypeTasksOnDisplay = "/ALL/";
		}

		else if (taskAction.equalsIgnoreCase("VIEW")) {
			String taskDescription = userInputElements.getTaskDescription()
					.toLowerCase();
			if (taskDescription == "all") {
				newTypeTasksOnDisplay = "/ALL/";
			} else if (taskDescription == "star") {
				newTypeTasksOnDisplay = "/STAR/";
			} else if (taskDescription == "deadline") {
				newTypeTasksOnDisplay = "/DEADLINE/";
			} else if (taskDescription == "finished") {
				newTypeTasksOnDisplay = "/FINISHED/";
			} else {
				newTypeTasksOnDisplay = typeTasksOnDisplay;
			}
		}

		else if (taskAction.equalsIgnoreCase("SEARCH")) {
			newTypeTasksOnDisplay = userInputElements.getTaskDescription()
					.toLowerCase();
		}

		else {
			newTypeTasksOnDisplay = typeTasksOnDisplay;
		}

		return newTypeTasksOnDisplay;
	}

	private void prepareForUndo(UserInputElements userInputElements,
			List<Task> tasksInTempStorage,
			List<List<Task>> snapshotOfTasks) {
		String command = userInputElements.getTaskAction().name().toLowerCase();
		
		if (command.equals("add") || command.equals("delete")
				|| command.equals("update")) {
			
			if (snapshotOfTasks.size() < 3) {
				snapshotOfTasks.add(new ArrayList<Task>(tasksInTempStorage));
			} else if (snapshotOfTasks.size() == 3) {
				snapshotOfTasks.remove(0);
				snapshotOfTasks.add(new ArrayList<Task>(tasksInTempStorage));
			} else {
				TaskO.taskOMainScreen.appendOutput("problem with undo");
			}
		}
	}

	/**
	 * Logic for Calling class objects for respective operations class
	 * 
	 * @param operation
	 * @param userInputElements
	 * @param typeTasksOnDisplay
	 * @param typeTasksOnDisplay
	 * @param snapshotOfTasks
	 * @throws IOException
	 */
	// later, change the test case for the method and not as the constructor
	private void executeCommand(UserInputElements userInputElements,
			List<Task> tasksInTempStorage, List<Task> tasksOnDisplay,
			String typeTasksOnDisplay, List<List<Task>> snapshotOfTasks) {
		String message = "";

		UserInputElements.TaskAction command = userInputElements
				.getTaskAction();

		if (command == command.ADD) {
			AddTask addTask = new AddTask();
			addTask.execute(userInputElements, tasksInTempStorage,
					tasksOnDisplay, typeTasksOnDisplay);
			this.printToTable(tasksOnDisplay);
		} else if (command == command.DELETE) {
			DeleteTask deleteTask = new DeleteTask();
			deleteTask.execute(userInputElements, tasksInTempStorage,
					tasksOnDisplay);
			this.printToTable(tasksOnDisplay);
		} else if (command == command.UPDATE) {
			UpdateTask updateTask = new UpdateTask();
			updateTask.execute(userInputElements, tasksInTempStorage,
					tasksOnDisplay, typeTasksOnDisplay);
			this.printToTable(tasksOnDisplay);
		} else if (command == command.VIEW) {
			ViewTask viewTask = new ViewTask();
			viewTask.execute(userInputElements, tasksInTempStorage,
					tasksOnDisplay);
			this.printToTable(tasksOnDisplay);
		} else if (command == command.SEARCH) {
			System.out.println("searching");
			SearchTask searchTask = new SearchTask();
			searchTask.execute(tasksInTempStorage, tasksOnDisplay,
					typeTasksOnDisplay);
			this.printToTable(tasksOnDisplay);
		} else if (command == command.UNDO) {
			UndoTask undoTask = new UndoTask();
			undoTask.execute(userInputElements, tasksInTempStorage,
					tasksOnDisplay, typeTasksOnDisplay, snapshotOfTasks);
			this.printToTable(tasksOnDisplay);
		} else if (command == command.SYNC) {
			GoogleCalendar googleCalendar = new GoogleCalendar(
					userInputElements);
		} else {
			TaskO.taskOMainScreen.appendOutput(ERROR_INVALID_INPUT);
		}

	}

	private void printToTable(List<Task> tasksOnDisplay) {
            TaskO.taskOMainScreen.writeTable(tasksOnDisplay);
	}
}